﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================

using Caffeine.Core.Test.TestModel;
using Caffeine.Core.Test.TestModel.PropertyRegistrations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Caffeine.Core.Test
{
    [TestClass]
    public class ModelGraphTester
    {
        [TestMethod]
        public void GetChildrenTests()
        {
            ModelForGraphTests viewModel = Creator.Create<ModelForGraphTests>();
            IEnumerable<ModelBase> children = viewModel.GetChildren();
            Assert.AreEqual(children.Count(), 0);

            viewModel.Child1.AssignCommitted(Creator.Create<ModelForGraphTests>());
            viewModel.Child1.Value = null;

            viewModel.Child2.Value = Creator.Create<ModelForGraphTests>();

            viewModel.Child3.AssignCommitted(Creator.Create<ModelForGraphTests>());
            viewModel.Child3.Value = Creator.Create<ModelForGraphTests>();

            viewModel.Child4.AssignCommitted(Creator.Create<ModelForGraphTests>());

            viewModel.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>(), true);
            viewModel.ChildrenCollection1.RemoveAt(0);

            viewModel.ChildrenCollection2.Add(Creator.Create<ModelForGraphTests>());

            viewModel.ChildrenCollection3.Add(Creator.Create<ModelForGraphTests>());
            viewModel.ChildrenCollection3.Add(Creator.Create<ModelForGraphTests>());
            viewModel.ChildrenCollection3.Add(Creator.Create<ModelForGraphTests>(), true);
            viewModel.ChildrenCollection3.Add(Creator.Create<ModelForGraphTests>(), true);
            viewModel.ChildrenCollection3.Add(Creator.Create<ModelForGraphTests>(), true);
            viewModel.ChildrenCollection3.Add(Creator.Create<ModelForGraphTests>(), true);
            viewModel.ChildrenCollection3.RemoveAt(1);
            viewModel.ChildrenCollection3.RemoveAt(1);

            children = viewModel.GetChildren().ToList();
            Assert.AreEqual(children.Count(), 8);
            Assert.AreEqual(children.ElementAt(0), viewModel.Child2.Value);
            Assert.AreEqual(children.ElementAt(1), viewModel.Child3.Value);
            Assert.AreEqual(children.ElementAt(2), viewModel.Child4.Value);
            Assert.AreEqual(children.ElementAt(3), viewModel.ChildrenCollection2[0]);
            Assert.AreEqual(children.ElementAt(4), viewModel.ChildrenCollection3[0]);
            Assert.AreEqual(children.ElementAt(5), viewModel.ChildrenCollection3[1]);
            Assert.AreEqual(children.ElementAt(6), viewModel.ChildrenCollection3[2]);
            Assert.AreEqual(children.ElementAt(7), viewModel.ChildrenCollection3[3]);

            children = viewModel.GetChildren(ModelStates.Added).ToList();
            Assert.AreEqual(children.Count(), 4);
            Assert.AreEqual(children.ElementAt(0), viewModel.Child2.Value);
            Assert.AreEqual(children.ElementAt(1), viewModel.Child3.Value);
            Assert.AreEqual(children.ElementAt(2), viewModel.ChildrenCollection2[0]);
            Assert.AreEqual(children.ElementAt(3), viewModel.ChildrenCollection3[0]);

            children = viewModel.GetChildren(ModelStates.Committed).ToList();
            Assert.AreEqual(children.Count(), 4);
            Assert.AreEqual(children.ElementAt(0), viewModel.Child4.Value);
            Assert.AreEqual(children.ElementAt(1), viewModel.ChildrenCollection3[1]);
            Assert.AreEqual(children.ElementAt(2), viewModel.ChildrenCollection3[2]);
            Assert.AreEqual(children.ElementAt(3), viewModel.ChildrenCollection3[3]);

            children = viewModel.GetChildren(ModelStates.Removed).ToList();
            Assert.AreEqual(children.Count(), 4);
            Assert.AreEqual(children.ElementAt(0), viewModel.Child1.CommittedValue);
            Assert.AreEqual(children.ElementAt(1), viewModel.Child3.CommittedValue);
            Assert.AreEqual(children.ElementAt(2), viewModel.ChildrenCollection1.RemovedModels.ElementAt(0));
            Assert.AreEqual(children.ElementAt(3), viewModel.ChildrenCollection3.RemovedModels.ElementAt(0));

            children = viewModel.GetChildren(ModelStates.Added | ModelStates.Removed);
            Assert.AreEqual(children.Count(), 8);
            Assert.AreEqual(children.ElementAt(0), viewModel.Child1.CommittedValue);
            Assert.AreEqual(children.ElementAt(1), viewModel.Child2.Value);
            Assert.AreEqual(children.ElementAt(2), viewModel.Child3.Value);
            Assert.AreEqual(children.ElementAt(3), viewModel.Child3.CommittedValue);
            Assert.AreEqual(children.ElementAt(4), viewModel.ChildrenCollection1.RemovedModels.ElementAt(0));
            Assert.AreEqual(children.ElementAt(5), viewModel.ChildrenCollection2[0]);
            Assert.AreEqual(children.ElementAt(6), viewModel.ChildrenCollection3[0]);
            Assert.AreEqual(children.ElementAt(7), viewModel.ChildrenCollection3.RemovedModels.ElementAt(0));

            children = viewModel.GetChildren(ModelStates.Committed | ModelStates.Removed);
            Assert.AreEqual(children.Count(), 8);
            Assert.AreEqual(children.ElementAt(0), viewModel.Child1.CommittedValue);
            Assert.AreEqual(children.ElementAt(1), viewModel.Child3.CommittedValue);
            Assert.AreEqual(children.ElementAt(2), viewModel.Child4.Value);
            Assert.AreEqual(children.ElementAt(3), viewModel.ChildrenCollection1.RemovedModels.ElementAt(0));
            Assert.AreEqual(children.ElementAt(4), viewModel.ChildrenCollection3[1]);
            Assert.AreEqual(children.ElementAt(5), viewModel.ChildrenCollection3[2]);
            Assert.AreEqual(children.ElementAt(6), viewModel.ChildrenCollection3[3]);
            Assert.AreEqual(children.ElementAt(7), viewModel.ChildrenCollection3.RemovedModels.ElementAt(0));

            children = viewModel.GetChildren(ModelStates.Added | ModelStates.Committed | ModelStates.Removed);
            Assert.AreEqual(children.Count(), 12);
            Assert.AreEqual(children.ElementAt(0), viewModel.Child1.CommittedValue);
            Assert.AreEqual(children.ElementAt(1), viewModel.Child2.Value);
            Assert.AreEqual(children.ElementAt(2), viewModel.Child3.Value);
            Assert.AreEqual(children.ElementAt(3), viewModel.Child3.CommittedValue);
            Assert.AreEqual(children.ElementAt(4), viewModel.Child4.Value);
            Assert.AreEqual(children.ElementAt(5), viewModel.ChildrenCollection1.RemovedModels.ElementAt(0));
            Assert.AreEqual(children.ElementAt(6), viewModel.ChildrenCollection2[0]);
            Assert.AreEqual(children.ElementAt(7), viewModel.ChildrenCollection3[0]);
            Assert.AreEqual(children.ElementAt(8), viewModel.ChildrenCollection3[1]);
            Assert.AreEqual(children.ElementAt(9), viewModel.ChildrenCollection3[2]);
            Assert.AreEqual(children.ElementAt(10), viewModel.ChildrenCollection3[3]);
            Assert.AreEqual(children.ElementAt(11), viewModel.ChildrenCollection3.RemovedModels.ElementAt(0));
        }

        [TestMethod]
        public void GetChildrenInGraphTest()
        {
            ModelGraphContainer graphContainer = new ModelGraphContainer();
            graphContainer.CommitAll();
            IEnumerable<ModelBase> children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed | ModelStates.Committed, Int32.MaxValue).ToList();

            Int32 index = 0;
            Assert.AreEqual(children.Count(), 18);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAD);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCBA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed | ModelStates.Committed, 0).ToList();

            index = 0;
            Assert.AreEqual(children.Count(), 3);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed | ModelStates.Committed, 1).ToList();

            index = 0;
            Assert.AreEqual(children.Count(), 9);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed | ModelStates.Committed, 2).ToList();

            index = 0;
            Assert.AreEqual(children.Count(), 14);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCBA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed | ModelStates.Committed, 3).ToList();

            index = 0;
            Assert.AreEqual(children.Count(), 18);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAD);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCBA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed | ModelStates.Committed, 4).ToList();

            index = 0;
            Assert.AreEqual(children.Count(), 18);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAD);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCBA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed, Int32.MaxValue).ToList();

            index = 0;
            Assert.AreEqual(children.Count(), 18);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAD);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCBA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            graphContainer = new ModelGraphContainer();
            graphContainer.Root.ChildrenCollection1.Commit(graphContainer.ModelA);
            graphContainer.ModelCC.ChildrenCollection1.Commit(graphContainer.ModelCCB);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);

            graphContainer.ModelC.ChildrenCollection1.Commit(graphContainer.ModelCC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);

            graphContainer.Root.ChildrenCollection1.Commit(graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 4);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            graphContainer.ModelA.ChildrenCollection1.Commit(graphContainer.ModelAB);
            graphContainer.ModelAB.ChildrenCollection1.Commit(graphContainer.ModelABA);
            graphContainer.ModelABA.ChildrenCollection1.Commit(graphContainer.ModelABAD);
            graphContainer.ModelAB.ChildrenCollection1.Commit(graphContainer.ModelABB);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 8);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAD);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed, 0).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 2);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed, 1).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 4);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed, 2).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 7);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed, 3).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 8);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAD);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 9);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added, 0).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added, 1).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 5);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added, 2).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 6);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added, 3).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 9);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Removed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 0);

            graphContainer.ModelABA.ChildrenCollection1.Remove(graphContainer.ModelABAD);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Removed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABAD);

            graphContainer.ModelAB.ChildrenCollection1.Remove(graphContainer.ModelABA);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Removed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);

            graphContainer.ModelAB.ChildrenCollection1.Remove(graphContainer.ModelABB);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Removed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 2);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Removed, 0).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 0);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Removed, 1).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 0);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Removed, 2).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 2);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);

            graphContainer.ModelC.ChildrenCollection1.Remove(graphContainer.ModelCA);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Removed, 2).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 2);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 7);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed, 0).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed, 1).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 4);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Added | ModelStates.Removed, 2).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 7);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Removed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 7);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Removed, 0).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 2);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Removed, 1).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 4);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Removed, 2).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 7);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Added, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 10);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Added, 0).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 3);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Added, 1).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 8);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Added, 2).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 10);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Added | ModelStates.Removed, Int32.MaxValue).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 12);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Added | ModelStates.Removed, 0).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 3);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Added | ModelStates.Removed, 1).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 8);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);

            children = graphContainer.Root.GetChildrenInGraph(ModelStates.Committed | ModelStates.Added | ModelStates.Removed, 2).ToList();
            index = 0;
            Assert.AreEqual(children.Count(), 12);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelABB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelAC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCA);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCCB);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelCC);
            Assert.AreEqual(children.ElementAt(index++), graphContainer.ModelC);
        }

        [TestMethod]
        public void GetChildrenInGraphTest2()
        {
            ModelForGraphTests viewModel = Creator.Create<ModelForGraphTests>();
            viewModel.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());
            viewModel.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>(), true);
            viewModel.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>(), true);
            viewModel.ChildrenCollection1.RemoveAt(2);

            IEnumerable<ModelBase> children = viewModel.GetChildrenInGraph();
            Assert.AreEqual(children.Count(), 2);
            Assert.AreEqual(children.ElementAt(0), viewModel.ChildrenCollection1[0]);
            Assert.AreEqual(children.ElementAt(1), viewModel.ChildrenCollection1[1]);

            children = viewModel.GetChildrenInGraph(ModelStates.Removed);
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(0), viewModel.ChildrenCollection1.RemovedModels.ElementAt(0));

            viewModel.ChildrenCollection1[1].TagName = "NameToLookFor";
            children = viewModel.GetChildrenInGraph("WrongName");
            Assert.AreEqual(children.Count(), 0);

            children = viewModel.GetChildrenInGraph("NameToLookFor");
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(0), viewModel.ChildrenCollection1[1]);

            viewModel.ChildrenCollection1[0].TagName = "NameToLookFor";
            viewModel.ChildrenCollection1.RemovedModels.ElementAt(0).TagName = "NameToLookFor";
            children = viewModel.GetChildrenInGraph("NameToLookFor");
            Assert.AreEqual(children.Count(), 2);
            Assert.AreEqual(children.ElementAt(0), viewModel.ChildrenCollection1[0]);
            Assert.AreEqual(children.ElementAt(1), viewModel.ChildrenCollection1[1]);

            children = viewModel.GetChildrenInGraph("NameToLookFor", ModelStates.Removed);
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(0), viewModel.ChildrenCollection1.RemovedModels.ElementAt(0));

            children = viewModel.GetChildrenInGraph("NameToLookFor", ModelStates.Added);
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(0), viewModel.ChildrenCollection1[0]);

            children = viewModel.GetChildrenInGraph("NameToLookFor", ModelStates.Committed);
            Assert.AreEqual(children.Count(), 1);
            Assert.AreEqual(children.ElementAt(0), viewModel.ChildrenCollection1[1]);
        }

        [TestMethod]
        public void GetChildrenInGraphTests3()
        {
            ModelGraphContainer container = new ModelGraphContainer();
            container.CommitAll();
            container.ModelABAA.Child1.Value = Creator.Create<ModelForGraphTests>();
            container.ModelABAA.Child1.Value.TagName = "NameToSearchFor";
            container.ModelC.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());
            container.ModelC.ChildrenCollection1[3].TagName = "NameToSearchFor";
            container.ModelC.ChildrenCollection2.Add(Creator.Create<ModelForGraphTests>());
            container.ModelC.ChildrenCollection2[0].TagName = "NameToSearchFor";

            IEnumerable<ModelBase> children = container.Root.GetChildrenInGraph("NameToSearchFor", ModelStates.Added, Int32.MaxValue);
            Assert.AreEqual(children.Count(), 3);
            Assert.AreEqual(children.ElementAt(0), container.ModelABAA.Child1.Value);
            Assert.AreEqual(children.ElementAt(1), container.ModelC.ChildrenCollection1[3]);
            Assert.AreEqual(children.ElementAt(2), container.ModelC.ChildrenCollection2[0]);

            children = container.Root.GetChildrenInGraph("NameToSearchFor", ModelStates.Added, 0);
            Assert.AreEqual(children.Count(), 0);

            children = container.Root.GetChildrenInGraph("NameToSearchFor", ModelStates.Added, 2);
            Assert.AreEqual(children.Count(), 2);
            Assert.AreEqual(children.ElementAt(0), container.ModelC.ChildrenCollection1[3]);
            Assert.AreEqual(children.ElementAt(1), container.ModelC.ChildrenCollection2[0]);

            children = container.Root.GetChildrenInGraph("NameToSearchFor", ModelStates.Added, 4);
            Assert.AreEqual(children.Count(), 3);
            Assert.AreEqual(children.ElementAt(0), container.ModelABAA.Child1.Value);
            Assert.AreEqual(children.ElementAt(1), container.ModelC.ChildrenCollection1[3]);
            Assert.AreEqual(children.ElementAt(2), container.ModelC.ChildrenCollection2[0]);

            ModelBase child = container.Root.GetChild("NameToSearchFor");
            Assert.AreEqual(child, container.ModelABAA.Child1.Value);

            child = container.Root.GetChild("WrongName");
            Assert.IsNull(child);
        }

        [TestMethod]
        public void GetRootTest()
        {
            ModelForGraphTests viewModel = Creator.Create<ModelForGraphTests>();
            Assert.IsNull(viewModel.GetRoot());
            viewModel.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());
            Assert.AreEqual(viewModel, viewModel.ChildrenCollection1[0].GetRoot());
            viewModel.ChildrenCollection1[0].ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());
            Assert.AreEqual(viewModel, viewModel.ChildrenCollection1[0].ChildrenCollection1[0].GetRoot());
        }

        [TestMethod]
        public void CommitGraphTest()
        {
            ModelForGraphTests viewModel = Creator.Create<ModelForGraphTests>();
            viewModel.CommitGraph();

            viewModel.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());
            viewModel.Child1.Value = Creator.Create<ModelForGraphTests>();
            Assert.IsTrue(viewModel.IsDirty);
            Assert.IsFalse(viewModel.IsDirtyWithin);

            viewModel.CommitGraph();
            Assert.IsFalse(viewModel.IsDirty);
            Assert.IsFalse(viewModel.IsDirtyWithin);

            viewModel.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());
            viewModel.ChildrenCollection1[0].ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());
            viewModel.ChildrenCollection1[0].ChildrenCollection1[0].StringProperty.Value = "SomeValue";
            viewModel.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>(), true);
            viewModel.ChildrenCollection1.RemoveAt(2);
            viewModel.ChildrenCollection1.RemovedModels.ElementAt(0).ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());

            viewModel.Child1.Value = Creator.Create<ModelForGraphTests>();
            viewModel.Child1.Value.Child1.Value = Creator.Create<ModelForGraphTests>();
            viewModel.Child1.CommittedValue.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());
            viewModel.Child1.CommittedValue.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>(), true);
            viewModel.Child1.CommittedValue.ChildrenCollection1[0].StringProperty.Value = "SomeValue";

            viewModel.CommitGraph();
            Assert.IsFalse(viewModel.IsDirty);
            Assert.IsFalse(viewModel.IsDirtyWithin);
        }

        [TestMethod]
        public void CommitGraphTest2()
        {
            ModelGraphContainer container = new ModelGraphContainer();
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Added).Count(), 3);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Committed).Count(), 0);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Removed).Count(), 0);
            Assert.IsTrue(container.Root.IsDirty);
            Assert.IsTrue(container.Root.IsDirtyWithin);

            container.Root.CommitGraph();

            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Added).Count(), 0);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Committed).Count(), 18);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Removed).Count(), 0);
            Assert.IsFalse(container.Root.IsDirty);
            Assert.IsFalse(container.Root.IsDirtyWithin);

            container.ModelABAA.StringProperty.Value = "SomeValue";
            Assert.IsTrue(container.Root.IsDirtyWithin);

            container.Root.CommitGraph();
            Assert.IsFalse(container.Root.IsDirtyWithin);

            container.ModelABB.StringProperty.Value = "SomeValue";
            container.ModelABB.Child1.Value = Creator.Create<ModelForGraphTests>();
            container.ModelAB.ChildrenCollection1.Remove(container.ModelABB);
            Assert.IsTrue(container.Root.IsDirtyWithin);

            container.Root.CommitGraph();
            Assert.IsFalse(container.Root.IsDirtyWithin);
            Assert.IsTrue(container.ModelABB.IsDirty);

            container.ModelABB.CommitGraph();
            container.ModelABB.StringProperty.Value = "SomeNewValue";

            Assert.IsFalse(container.Root.IsDirtyWithin);
            Assert.IsTrue(container.ModelABB.IsDirty);

            container.ModelCBA.Child1.Value = Creator.Create<ModelForGraphTests>();
            container.ModelCBA.Child1.Value.Child1.AssignCommitted(Creator.Create<ModelForGraphTests>());
            container.ModelCBA.Child1.Value.Child1.Value.StringProperty.Value = "SomeValue";
            container.ModelCBA.Child1.Value.Child1.Value.Child1.Value = Creator.Create<ModelForGraphTests>();
            Assert.IsTrue(container.Root.IsDirtyWithin);

            container.Root.CommitGraph();
            Assert.IsFalse(container.Root.IsDirtyWithin);
        }

        [TestMethod]
        public void ResetGraphTest1()
        {
            ModelWithNoProperties viewModel = Creator.Create<ModelWithNoProperties>();
            viewModel.ResetGraph();
        }

        [TestMethod]
        public void ResetGraphTest2()
        {
            ModelGraphContainer container = new ModelGraphContainer();
            container.Root.CommitGraph();

            Assert.IsFalse(container.Root.IsDirty);
            Assert.IsFalse(container.Root.IsDirtyWithin);

            container.Root.ResetGraph();

            Assert.IsFalse(container.Root.IsDirty);
            Assert.IsFalse(container.Root.IsDirtyWithin);

            container.ModelCBA.Child1.AssignCommitted(Creator.Create<ModelForGraphTests>());
            container.ModelCBA.Child1.Value = Creator.Create<ModelForGraphTests>();

            container.ModelABA.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>(), true);
            container.ModelABA.ChildrenCollection1.RemoveAt(container.ModelABA.ChildrenCollection1.Count - 1);

            ModelForGraphTests newChild = Creator.Create<ModelForGraphTests>();
            newChild.Child1.Value = Creator.Create<ModelForGraphTests>();
            container.ModelABA.ChildrenCollection1.Add(newChild);

            container.ModelAA.StringProperty.Value = "SomeValue";
            container.ModelB.StringProperty.Value = "SomeValue";
            container.Root.StringProperty.Value = "SomeValue";

            Assert.IsTrue(container.Root.IsDirty);
            Assert.IsTrue(container.Root.IsDirtyWithin);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Added).Count(), 2);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Committed).Count(), 18);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Removed).Count(), 2);

            container.Root.ResetGraph();

            Assert.IsFalse(container.Root.IsDirty);
            Assert.IsFalse(container.Root.IsDirtyWithin);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Added).Count(), 0);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Committed).Count(), 20);
            Assert.AreEqual(container.Root.GetChildrenInGraph(ModelStates.Removed).Count(), 0);
            Assert.IsTrue(newChild.IsDirty);
        }

        [TestMethod]
        public void ValidateGraphTest1()
        {
            ModelWithNoProperties viewModel = Creator.Create<ModelWithNoProperties>();
            viewModel.ValidateGraph();
        }

        [TestMethod]
        public void ValidateGraphTest2()
        {
            ModelGraphContainer container = new ModelGraphContainer();
            container.Root.ValidateGraph();
            Assert.IsFalse(container.Root.IsInvalid);
            Assert.IsFalse(container.Root.IsInvalidWithin);

            container.Root.CommitGraph();

            ModelForGraphTests childModel = Creator.Create<ModelForGraphTests>();
            childModel.Child2.Value = Creator.Create<ModelForGraphTests>();
            childModel.Child2.Value.Child3.Value = Creator.Create<ModelForGraphTests>();
            childModel.Child2.Value.Child3.ValidationMethod = delegate(ModelProperty<ModelForGraphTests> property, ref IEnumerable<ValidationError> errors, ref Boolean isValid)
            {
                isValid = false;
            };

            container.ModelAA.Child1.Value = childModel;
            container.ModelAA.ValidateGraph();
            Assert.IsTrue(container.Root.IsInvalidWithin);

            childModel.Child2.Value.Child3.ValidationMethod = null;
            container.ModelAA.ValidateGraph();
            Assert.IsFalse(container.Root.IsInvalidWithin);

            container.Root.CommitGraph();

            childModel.Child2.Value.Child3.ValidationMethod = delegate(ModelProperty<ModelForGraphTests> property, ref IEnumerable<ValidationError> errors, ref Boolean isValid)
            {
                isValid = false;
            };
            container.ModelAA.ValidateGraph();
            Assert.IsTrue(container.Root.IsInvalidWithin);
        }

        [TestMethod]
        public void ReleaseObserversForGraphTest()
        {
            ModelGraphContainer container = new ModelGraphContainer();
            container.Root.CommitGraph();

            Boolean propertyChangedCalled = false;
            Boolean commandPropertyChangeCalled = false;
            Boolean commandCanExecuteChangeCalled = false;

            container.ModelAB.PropertyChanged += delegate
            {
                propertyChangedCalled = true;
            };

            container.ModelAB.Child1.PropertyChanged += delegate
            {
                propertyChangedCalled = true;
            };

            container.ModelABAA.Command.CanExecuteChanged += delegate
            {
                commandCanExecuteChangeCalled = true;
            };

            container.ModelABAA.Command.PropertyChanged += delegate
            {
                commandPropertyChangeCalled = true;
            };

            container.ModelABAA.Command.RaiseCanExecuteChanged();
            Assert.IsTrue(commandCanExecuteChangeCalled);
            commandCanExecuteChangeCalled = false;

            container.ModelABAA.Command.CanExecute(null);
            Assert.IsTrue(commandPropertyChangeCalled);
            commandPropertyChangeCalled = false;

            container.ModelAB.Child1.Value = Creator.Create<ModelForGraphTests>();
            Assert.IsTrue(propertyChangedCalled);
            propertyChangedCalled = false;

            container.ModelCA.ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());

            container.ModelCA.ChildrenCollection1[0].ChildrenCollection1.CollectionChanged += delegate
            {
                propertyChangedCalled = true;
            };

            container.ModelCA.ChildrenCollection1[0].ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());

            Assert.IsTrue(propertyChangedCalled);
            propertyChangedCalled = false;

            container.ModelCA.ChildrenCollection1[0].ChildrenCollection1[0].TagName = "ModelToWatch";
            container.ModelCA.ChildrenCollection1[0].ChildrenCollection1[0].PropertyChanged += delegate
            {
                propertyChangedCalled = true;
            };

            container.ModelCB.Child1.AssignCommitted(Creator.Create<ModelForGraphTests>());
            container.ModelCB.Child1.Value = null;
            container.ModelCB.Child1.CommittedValue.Child1.Value = Creator.Create<ModelForGraphTests>();
            container.ModelCB.Child1.CommittedValue.Child1.Value.Child1.Value = Creator.Create<ModelForGraphTests>();
            container.ModelCB.Child1.CommittedValue.CommitGraph();
            container.ModelCB.Child1.CommittedValue.Child1.Value.Child1.Value.PropertyChanged += delegate
            {
                propertyChangedCalled = true;
            };

            propertyChangedCalled = false;
            container.ModelCB.Child1.CommittedValue.Child1.Value.Child1.Value.StringProperty.Value = "SomeValue";
            Assert.IsTrue(propertyChangedCalled);

            propertyChangedCalled = false;
            container.Root.ReleaseObserversForGraph();

            container.ModelCB.Child1.CommittedValue.Child1.Value.Child1.Value.StringProperty.Value = null;
            Assert.IsFalse(propertyChangedCalled);

            container.ModelCA.ChildrenCollection1[0].ChildrenCollection1[0].StringProperty.Value = "SomeValue";
            Assert.IsFalse(propertyChangedCalled);

            container.ModelCA.ChildrenCollection1[0].ChildrenCollection1.Add(Creator.Create<ModelForGraphTests>());
            Assert.IsFalse(propertyChangedCalled);

            container.Root.ResetGraph();
            Assert.IsFalse(propertyChangedCalled);

            container.ModelABAA.Command.RaiseCanExecuteChanged();
            Assert.IsFalse(commandCanExecuteChangeCalled);

            container.ModelABAA.Command.CanExecute(null);
            Assert.IsFalse(commandPropertyChangeCalled);
        }
    }
}
